package edu.nepu.bigdata.compile;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;

public class DynamicCompileAndRun {

    private static String javaFilePath;
    private static String classFilePath;
    private static String fullClassName;
    private static String methodName;
    private static Method method = null;
    private static Object instance = null;
    private static final Logger logger = LoggerFactory.getLogger(DynamicCompileAndRun.class);
    public DynamicCompileAndRun(String className, String methodName) {
        javaFilePath = "./java_file/";
        classFilePath = "./class_file/";
        fullClassName = className;
        DynamicCompileAndRun.methodName = methodName;
    }
    //public void compile() {
    //    try {
    //        // com.ishansong.bigdata.compile.DynamicCompileAndRun
    //        String[] split = fullClassName.split("\\.");
    //        // 外部 Java 文件的路径
    //        String sourceFilePath = javaFilePath + split[split.length-1] + ".java";
    //        File sourceFile = new File(sourceFilePath);
    //        // 1. 编译 Java 文件
    //        compileJavaFile(sourceFilePath);
    //        // 2. 加载编译后的类
    //        URLClassLoader classLoader = new URLClassLoader(new URL[]{new File(javaFilePath + split[split.length-1] + ".class").toURI().toURL()});
    //        Class<?> clazz = classLoader.loadClass(fullClassName);
    //
    //        // 3. 创建类的实例并调用方法
    //        instance = clazz.getDeclaredConstructor().newInstance();
    //        method = clazz.getMethod(methodName, int.class,long.class,String.class,String.class);
    //        // 清理生成的 .class 文件
    //        //new File(javaFilePath + split[split.length-1] + ".class").delete();
    //    } catch (Exception e) {
    //        e.printStackTrace();
    //    }
    //}

    private void compileJavaFile() {
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        if (compiler == null) {
            System.out.println("No Java compiler available.");
            return;
        }

        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
        Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjects(new File(javaFilePath + fullClassName + ".java"));

        // 创建输出目录
        File outputDir = new File(classFilePath);
        if (!outputDir.exists()) {
            outputDir.mkdirs();
        } else {
            Path directory = Paths.get(classFilePath);
            try (DirectoryStream<Path> stream = Files.newDirectoryStream(directory)) {
                for (Path entry : stream) {
                    Files.delete(entry); // 删除文件或子目录
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        // 进行编译，并指定输出目录
        boolean success = compiler.getTask(null, fileManager, null, Arrays.asList("-d", classFilePath),null, compilationUnits).call();
        if (success) {
            System.out.println("Compilation successful.");
        } else {
            System.out.println("Compilation failed.");
        }

        try {
            fileManager.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void run(Class<?>... parameterTypes) throws Exception{
        // 使用包含 ProcessData.class 文件的目录
        File file = new File(classFilePath);
        URL url = file.toURI().toURL();

        // 创建 URLClassLoader
        URLClassLoader classLoader = new URLClassLoader(new URL[]{url});

        // 加载类（确保使用完全限定名，如果在包内）
        Class<?> processData = classLoader.loadClass(fullClassName);

        // 获取方法并调用
        method = processData.getMethod(methodName, parameterTypes);
        instance = processData.newInstance();

        // 关闭类加载器
        classLoader.close();
    }

    /**
     * 处理kafka数据
     * @param partition 分区
     * @param offset 偏移量
     * @param key key
     * @param value record
     * @throws Exception
     */
    public void run(int partition, long offset, String key, String value) throws Exception{
        if (method == null || instance == null){
            compileJavaFile();
            run(int.class, long.class, String.class, String.class);
        }
        //logger.info("partition:{},offset:{},key:{},value:{}", partition, offset, key, value);
        //logger.info("method name {} , method param{}",method.getName(), method.getParameterCount());
        method.invoke(instance, partition,offset,key,value);
    }

    /**
     * 处理redis的数据
     * @param jedis 哨兵/单机
     * @param jedisCluster 集群模式
     * @throws Exception
     */
    public void run(Jedis jedis, JedisCluster jedisCluster) throws Exception{
        if (method == null || instance == null){
            compileJavaFile();
            run(Jedis.class, JedisCluster.class);
        }
        method.invoke(instance, jedis, jedisCluster);
    }
}
